package com.example.springbootquartz.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springbootquartz.common.Constant;
import com.example.springbootquartz.entity.ScheduleJob;
import com.example.springbootquartz.mapper.ScheduleJobMapper;
import com.example.springbootquartz.service.IQuartzJobService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;


@Slf4j
@Service
public class QuartzJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJob> implements IQuartzJobService {

	@Autowired
	private Scheduler scheduler;

	/**
	 * 立即执行的任务分组
	 */
	private static final String JOB_TEST_GROUP = "test_group";


	/**
	 * 保存&启动定时任务
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean saveScheduleJob(ScheduleJob quartzJob) {
		// DB设置修改
		quartzJob.setIDel(0);
		boolean success = this.save(quartzJob);
		if (success) {
			if (Constant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
				// 定时器添加
				this.schedulerAdd(quartzJob.getId(), quartzJob.getClassName().trim(), quartzJob.getCron().trim(), quartzJob.getParameter());
			}
		}
		return success;
	}

	/**
	 * 恢复定时任务
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean resumeJob(ScheduleJob quartzJob) {
		schedulerDelete(quartzJob.getId());
		schedulerAdd(quartzJob.getId(), quartzJob.getClassName().trim(), quartzJob.getCron().trim(), quartzJob.getParameter());
		quartzJob.setStatus(Constant.STATUS_NORMAL);
		return this.updateById(quartzJob);
	}

	/**
	 * 编辑&启停定时任务
	 * @throws SchedulerException 
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean editScheduleJob(ScheduleJob quartzJob) throws SchedulerException {
		if (Constant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
			schedulerDelete(quartzJob.getId());
			schedulerAdd(quartzJob.getId(), quartzJob.getClassName().trim(), quartzJob.getCron().trim(), quartzJob.getParameter());
		}else{
			scheduler.pauseJob(JobKey.jobKey(quartzJob.getId()));
		}
		return this.updateById(quartzJob);
	}

	/**
	 * 删除&停止删除定时任务
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean deleteStopJob(ScheduleJob job) {
		schedulerDelete(job.getId());
		boolean ok = this.removeById(job.getId());
		return ok;
	}

	@Override
	public void execute(ScheduleJob quartzJob) throws Exception {
		String jobName = quartzJob.getClassName().trim();
		Date startDate = new Date();
		String time = startDate.getTime()+"";
		String identity =  jobName + time;
		//0.1s执行1次
		startDate.setTime(startDate.getTime() + 100L);
		// 定义一个Trigger
		SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger()
				.withIdentity(identity, JOB_TEST_GROUP)
				.startAt(startDate)
				.build();
		// 构建job信息
		JobDetail jobDetail = JobBuilder.newJob(getClass(jobName).getClass()).withIdentity(identity).usingJobData("parameter", quartzJob.getParameter()).build();
		// 将trigger和 jobDetail 加入这个调度
		scheduler.scheduleJob(jobDetail, trigger);
		// 启动scheduler
		scheduler.start();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void pause(ScheduleJob quartzJob){
		schedulerDelete(quartzJob.getId());
		quartzJob.setStatus(Constant.STATUS_DISABLE);
		this.updateById(quartzJob);
	}

	/**
	 * 添加定时任务
	 *
	 * @param jobClassName
	 * @param cronExpression
	 * @param parameter
	 */
	private void schedulerAdd(String id, String jobClassName, String cronExpression, String parameter) {
		try {
			// 启动调度器
			scheduler.start();

			// 构建job信息
			JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(id).usingJobData("parameter", parameter).build();

			// 表达式调度构建器(即任务执行的时间)
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

			// 按新的cronExpression表达式构建一个新的trigger
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withSchedule(scheduleBuilder).build();

			scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			throw new RuntimeException("创建定时任务失败", e);
		} catch (RuntimeException e) {
			throw new RuntimeException(e.getMessage(), e);
		}catch (Exception e) {
			throw new RuntimeException("后台找不到该类名：" + jobClassName, e);
		}
	}

	/**
	 * 删除定时任务
	 * 
	 * @param id
	 */
	private void schedulerDelete(String id) {
		try {
			scheduler.pauseTrigger(TriggerKey.triggerKey(id));
			scheduler.unscheduleJob(TriggerKey.triggerKey(id));
			scheduler.deleteJob(JobKey.jobKey(id));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new RuntimeException("删除定时任务失败");
		}
	}

	private static Job getClass(String classname) throws Exception {
		Class<?> class1 = Class.forName(classname);
		return (Job) class1.newInstance();
	}

}
